package com.sengled.cloud.biz.union.mgt.api.config;

import com.sengled.cloud.biz.union.mgt.api.filter.JsonAuthenticationFilter;
import com.sengled.cloud.biz.union.mgt.common.util.Md5Util;
import com.sengled.cloud.biz.union.mgt.service.sys.impl.CustomUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.session.ExpiringSession;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;

import javax.annotation.Resource;

/**
 * Created by ti on 2017/10/9.
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
@EnableRedisHttpSession(maxInactiveIntervalInSeconds= 1 * 24 * 60 * 60)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Resource
    private FindByIndexNameSessionRepository<ExpiringSession> sessionRepository;



    @Bean
    UserDetailsService customUserService(){ //注册UserDetailsService 的bean
        return new CustomUserService();
    }

//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        super.configure(auth);
    //auth.userDetailsService(customUserService()); //user Details Service验证
//        auth.userDetailsService(customUserService()).passwordEncoder(new BCryptPasswordEncoder());
        /*.passwordEncoder(new PasswordEncoder(){
            @Override
            public String encode(CharSequence rawPassword) {

                return Md5Util.md5((String) rawPassword);
            }



            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return encodedPassword.equals(Md5Util.md5((String) rawPassword));
            }}); //user Details Service验证*/
//    }

    @Bean
    DaoAuthenticationProvider daoAuthenticationProvider(){
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(new PasswordEncoder(){
            @Override
            public String encode(CharSequence rawPassword) {
                return Md5Util.md5((String) rawPassword);
            }

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return encodedPassword.equals(Md5Util.md5((String) rawPassword));
            }});
        daoAuthenticationProvider.setUserDetailsService(customUserService());
        return daoAuthenticationProvider;
    }

    /*@Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("USER");
//        auth.inMemoryAuthentication().withUser("admin").password("root123").roles("ADMIN");
        auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");
    }*/

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        SessionManagementConfigurer<HttpSecurity> sessionManagement = http.sessionManagement();
        sessionManagement.sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
        sessionManagement.sessionFixation().migrateSession();
        sessionManagement.maximumSessions(10);

        http.csrf().disable();
        http.addFilterBefore(jsonAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);
        http.authenticationProvider(daoAuthenticationProvider());


        http.authorizeRequests()
                .anyRequest().authenticated() //任何请求,登录后可以访问
                .and()
                .formLogin().loginPage("/")
//                .successForwardUrl("/index")
                .successHandler(new MyAuthenticationSuccessHandler())
//                .failureHandler()
                .loginProcessingUrl("/api/v1/user/login").usernameParameter("username").passwordParameter("password").permitAll()
                .failureUrl("/login?error")
                .permitAll() //登录页面用户任意访问
                .and()
//                .sessionManagement()
//                .and()
//                .and()
                .logout().permitAll().logoutUrl("/api/app/v1/user/logout").logoutSuccessHandler(new MyLogoutSuccessHandler()); //注销行为任意访问

    }

    /*@Bean
    AuthenticationManager authenticationManager(
            ObjectPostProcessor<Object> objectPostProcessor,
            UserDetailsService userDetailsService) throws Exception {
        AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(objectPostProcessor);

        auth.userDetailsService(customUserService()).passwordEncoder(new PasswordEncoder(){
            @Override
            public String encode(CharSequence rawPassword) {
                return Md5Util.md5((String) rawPassword);
            }

            @Override
            public boolean matches(CharSequence rawPassword, StrinΩg encodedPassword) {
                return encodedPassword.equals(Md5Util.md5((String) rawPassword));
            }}); //user Details Service验证

        return auth.getOrBuild();
    }*/

    @Bean
    JsonAuthenticationFilter jsonAuthenticationFilter() throws Exception {
        JsonAuthenticationFilter filter = new JsonAuthenticationFilter();
        filter.setAuthenticationManager(authenticationManagerBean());
        filter.setPostOnly(true);
        filter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/api/v1/user/login", "POST"));
        filter.setAuthenticationFailureHandler(new MyAuthenticationFaildHandler());
        filter.setAuthenticationSuccessHandler(new MyAuthenticationSuccessHandler());
        ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlAuthenticationStrategy = new ConcurrentSessionControlAuthenticationStrategy(springSessionBackedSessionRegistry(sessionRepository) );
        concurrentSessionControlAuthenticationStrategy.setMaximumSessions(1);
        filter.setSessionAuthenticationStrategy(concurrentSessionControlAuthenticationStrategy);

        System.out.println("jsonAuthenticationFilter");
        return filter;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
        web.ignoring().antMatchers("/css/**","/fonts/**","/favicon/**","/js/**","/images/**","/druid/**","/img/**",
                    "/**/",
//                "/swagger-ui.html","/webjars/**","/swagger-resources/**","/v2/api-docs","/api/v1/**","/api/app/v1/**");
                "/swagger-ui.html","/webjars/**","/swagger-resources/**","/v2/api-docs","/api/v1/user/checkLogin");
    }

    @Bean
    @Autowired
    public SpringSessionBackedSessionRegistry springSessionBackedSessionRegistry(FindByIndexNameSessionRepository sessionRepository) {
        return new SpringSessionBackedSessionRegistry(sessionRepository);
    }

    public static void main(String[] args) {
        System.out.println(Md5Util.md5("string"));
    }
}
